03 Django 模板
模板的设计方式实现了 MVT(M: Model, V: View, T: Template) 的解耦, VT 有着 N:M 的关系,一个 V 可以调用任意 T,一个 T 可以供任意 V 使用。
模板处理分为两个过程:
- 加载 HTML
- 渲染数据
模板主要有两个部分:
- HTML 静态代码
- 模板语言,动态插入的代码段(挖坑、填坑)
模板中的动态代码段除了做基本的静态填充,还可以实现一些基本的运算,转换和逻辑。
静态页面:页面数据是本地固定的
动态页面:页面数据来源于后台服务器
模板中的变量: 视图转递给模板的数据,遵赛标识符规则
- 语法:{{ var }}
- 如果变量不存在,则插入空字符串
注意:在模板语言中,方法(函数)不能有参数,列表索引也不允许使用负索引。
- 方法(函数)不能有参数。如 str 有 upper 函数,不能用{{ str.upper() }} 调用,只能用 {{ str.upper }} 调用。
- 列表索引不允许使用负索引。如 items = ["apples", "bananas", "carrots"],获取 carrots 可以用 {{ items.2 }},不能用 {{ items.-1 }}
模板中的标签:
- 语法 {% tag %}
- 作用:
- 加载外部传入的变量
- 在输出中创建文本
- 控制循环(for)或逻辑(if)
if 语句:
单分支
{% if 表达式 %}
语句
{% endif %}
双分支
{% if 表达式 %}
语句
{% else %}
语句
{% endif%}
多分支
{% if 表达式 %}
语句
{% elif 表达式%}
语句
{% else %}
语句
{% endif %}
判断 ture 或 false
{% if today_is_weekend %}
<p> Welcom to the weekend!</p>
{% endif %}
使用 and, or, not
{% if athlete_list and coach_list %}
<p>Both athletes and coaches are available</p>
{% endif %}
{% if not athlete_list %}
<p>There are no athletes.</p>
{% endif %}
{% if athlete_list or coach_list %}
<p>There are some athletes or some coaches</p>
{% endif %}
使用 in, not in
{% if "bc" in "abcdef" %}
<p> This paragraph will be appear since "bc" is a substring of "abcdef" </p>
{% endif %}
{% if user not in users %}
<p> Assumed users is a list, this paragraph will be appear if user isn't an element of the list.</p>
{% endif %}
for 语句
{% for 变量 in 列表 %}
语句1
{% empty %}
语句2
{% endfor %}
# 变量在列表中时执行语句1,列表为空时执行语句2
?: 列表循环完后,会不会执行语句2。不管列表为何值,empty 后的语句总是执行?
当列表为空值是,才会执行 empty 后的语句。列表可以循环,则列表不为空,不执行 empty 后的语句。列表循环完后,列表的值不变,仍不为空值,empty 后的语句也不执行。
?: 如果,语句1 中有删除列表元素的操作呢?
一个特殊变量:****{{ forloop.counter }} 表示当前是第几次循环,从 1 开始。
{% for item in todo_list %}
<p> {{forloop.counter }}: {{ item }} </p>
{% endfor %}
{{ forloop.counter0 }}:当前是第几次循环,从 0 开始
{{ forloop.revcounter }}:当前是第几次循环,倒着数数,到 1 停
{{ forloop.revcounter0 }}:当前是第几次循环,倒着数数,到 0 停
{{ forloop.first }}:是否是第一个,布尔值
{{ forloop.last }}:是滞是最后一个,布尔值
{{ forloop.parentloop.counter }}:当前循环的父循环(上层循环)是第几次循环。也有 counter0, revcounter, revcounter0, first, last
# forloop.first
{% for object in objects %}
{% if forloop.first %}
<li class="first">
{% else %}
<li>
{% endif %}
{{ object }}</li>
{% endfor %}
# forloop.last
{% for link in links %}
{{ link }}{% if not forloop.last %}| {% endif %}
{% endfor%}
# forloop.parentloop
{% for country in countries %}
<table>
{% for city in country.city_list %}
<tr>
<td>Country #{{ forloop.parentloop.counter }}</td>
<td>City #{{ forloop.counter }}</td>
<td>{{ city }}</td>
</tr>
{% endfor %}
</table>
{% endfor %}
注释:
单行注释:{# 注释内容 #}
多行注释:
{% comment %}
内容
{% endcomment %}
过滤器:{{ var|过滤器 }}在变量显示前修改
加法过滤器,add: {{ value|add:2 }},value 加 2 。
没有减法过滤器,但可以加负值:{{ value|add:-2 }},value 减 2 。
全小写过滤器,lower:{{ name|lower }},name 所有字符转为小写。
全大写过滤器,upper:{{ name|upper }},name 所有字符转为大写。
可迭代变量的第一个值,first:{{ my_list|first }},my_list 的第一个值。
可以加多个过滤器:{{ my_list|firs|upper }},my_list 的第一个值全部大写(从左往右)。
截断,truncatechars:{{ bio | truncatechars: 30}},截取 bio 的前 30 个字符。
过滤器可以传递参数,参数需要使用引号引起来,join:{{ students | join: "="}}
默认值,default:{{ var|default:value }},var 为空值时,显示 value 的值
日期格式化输出,date:{{ dateVal | date: "y-m-d" }},按 y-m-d 格式将 dateVal 转换后输出(显示)
HTML 转义,safe
渲染成 html:{{ code|safe }}
关闭自动转义:{% autoescape off %} code {% endautoescape %}
打开自动转义:{% autoescape on %} code {% endautoescape %
模板继承
模板继承中包含 block,extends,include,block.super 等内容。
block
在父模板中使用 block 挖坑:block 后跟块(坑)名
{% block posName %} # posName 是这个块(坑)的名称
code
{% endblock %}
extends
在子模板中使用 extends继承父模板,写在开头位置。
{% extends '父模板路径' %}
然后再使用 block 将父模板中使用 block 挖得同名坑填上:
{% block posName %}
code
{% endblock %}
include
加载模板进行渲染,即将其他 htlm 文件内容加载进来,并放在 include 的位置。
{% include 'smeCode.html' %}
将 smeCode.html 的内容加到当前页面的 {% include "smeCode.html" %} 的位置,即用 smeCode.html 的内容替换 {% include "smeCode.html" %} 语句。应该解释清楚了吧。
block.super
block.super 是变量,使用时用 {{ }},获取父模板中 block 的内容:
{{ block.super }}
默认情况下,子模板的内容会覆盖父模板的内容,如果想将父模板的内容显示出来,需要用 block.super 将父模板的内容继承过来。